using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SeataNet.Core.Attributes;
using SeataNet.Core.Common;
using SeataNet.Core.Context;
using SeataNet.Core.Exceptions;
using SeataNet.Core.Protocol;
using SeataNet.Core.RPC;
using System.Reflection;
using System.Text.Json;

namespace SeataNet.Core.TCC
{
  /// <summary>
  /// TCC服务调用代理
  /// </summary>
  public class TccServiceProxy : DispatchProxy
  {
    private ILogger<TccServiceProxy>? _logger;
    private readonly IServiceProvider? _serviceProvider;
    private ITccTransactionManager? _transactionManager;
    private IRpcClientManager? _rpcClientManager;
    private TccServiceConfiguration? _configuration;
    private Type? _targetType;
    private string? _serviceName;

    protected override object Invoke(MethodInfo? targetMethod, object?[]? args)
    {
      return InvokeAsync(targetMethod, args).GetAwaiter().GetResult();
    }

    protected async Task<object> InvokeAsync(MethodInfo? targetMethod, object?[]? args)
    {
      if (targetMethod == null)
      {
        throw new ArgumentNullException(nameof(targetMethod));
      }

      if (args == null)
      {
        throw new ArgumentNullException(nameof(args));
      }

      string methodName = targetMethod.Name;
      Type returnType = targetMethod.ReturnType;

      // 检查是否是异步方法
      bool isAsync = returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>);
      Type resultType = isAsync ? returnType.GetGenericArguments()[0] : returnType;

      // 获取方法上的TccActionAttribute
      TccActionAttribute actionAttribute = targetMethod.GetCustomAttribute<TccActionAttribute>() ?? throw new InvalidOperationException($"方法 {methodName} 缺少 TccActionAttribute");

      // 获取当前事务上下文
      var xid = RootContext.GetXid();
      if (string.IsNullOrEmpty(xid))
      {
        throw new InvalidOperationException($"TCC服务调用必须在全局事务中执行");
      }

      var transactionContext = _transactionManager.GetTransactionContext(xid) ?? throw new InvalidOperationException($"找不到事务上下文: XID={xid}");

      // 创建分支上下文
      TccBranchContext branchContext = new()
      {
        BranchId = 0, // Will be set after registration
        ResourceId = $"{_serviceName}.{methodName}",
        ServiceName = _serviceName,
        MethodName = methodName,
        Phase = transactionContext.Phase,
        Args = args,
        CreatedTime = DateTime.UtcNow
      };

      // 注册分支事务
      BranchType branchType = GetBranchType(methodName);
      var branchId = await _transactionManager.BranchRegisterAsync(
          xid,
          branchContext.ResourceId,
          JsonSerializer.Serialize(args));

      if (branchId <= 0)
      {
        throw new TransactionException($"注册TCC分支事务失败");
      }

      branchContext.BranchId = branchId;

      try
      {
        // 根据当前阶段调用相应的方法
        object? result = null;

        result = (object)transactionContext.Phase switch
        {
          TccTransactionPhase.Try => await InvokeTryAsync(branchContext, args, resultType),
          TccTransactionPhase.Confirm => await InvokeConfirmAsync(branchContext, args, resultType),
          TccTransactionPhase.Cancel => await InvokeCancelAsync(branchContext, args, resultType),
          _ => throw new InvalidOperationException($"不支持的TCC事务阶段: {transactionContext.Phase}"),
        };

        // 报告分支状态
        var status = transactionContext.Phase == TccTransactionPhase.Try ?
                    TccBranchStatus.Registered :
                    TccBranchStatus.PhaseDone;

        var reportResult = await _transactionManager.BranchReportAsync(
            xid,
            branchContext.BranchId,
            status);

        if (!reportResult)
        {
          _logger.LogWarning($"报告TCC分支状态失败: XID={xid}, BranchId={branchContext.BranchId}");
        }

        return result;
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"TCC服务调用失败: Service={_serviceName}, Method={methodName}, Phase={transactionContext.Phase}");

        // 报告分支状态为失败
        var reportResult = await _transactionManager.BranchReportAsync(
            xid,
            branchContext.BranchId,
            TccBranchStatus.Failed);

        if (!reportResult)
        {
          _logger.LogWarning($"报告TCC分支失败状态失败: XID={xid}, BranchId={branchContext.BranchId}");
        }

        throw;
      }
    }

    private async Task<object> InvokeTryAsync(TccBranchContext branchContext, object[] args, Type resultType)
    {
      string tryMethodName = $"{branchContext.MethodName}{_configuration.TryMethodSuffix}";

      // 如果是本地服务，直接调用
      if (_configuration.IsLocalService)
      {
        return await InvokeLocalMethodAsync(tryMethodName, args, resultType);
      }

      // 否则通过RPC调用
      return await InvokeRpcMethodAsync(tryMethodName, args, resultType);
    }

    private async Task<object> InvokeConfirmAsync(TccBranchContext branchContext, object[] args, Type resultType)
    {
      string confirmMethodName = $"{branchContext.MethodName}{_configuration.ConfirmMethodSuffix}";

      // 如果是本地服务，直接调用
      if (_configuration.IsLocalService)
      {
        return await InvokeLocalMethodAsync(confirmMethodName, args, resultType);
      }

      // 否则通过RPC调用
      return await InvokeRpcMethodAsync(confirmMethodName, args, resultType);
    }

    private async Task<object> InvokeCancelAsync(TccBranchContext branchContext, object[] args, Type resultType)
    {
      string cancelMethodName = $"{branchContext.MethodName}{_configuration.CancelMethodSuffix}";

      // 如果是本地服务，直接调用
      if (_configuration.IsLocalService)
      {
        return await InvokeLocalMethodAsync(cancelMethodName, args, resultType);
      }

      // 否则通过RPC调用
      return await InvokeRpcMethodAsync(cancelMethodName, args, resultType);
    }

    private async Task<object?> InvokeLocalMethodAsync(string methodName, object[] args, Type resultType)
    {
      // 获取本地服务实例
      object service = _serviceProvider.GetService(_targetType) ?? throw new InvalidOperationException($"无法获取本地服务实例: {_targetType.Name}");

      // 获取方法
      MethodInfo method = _targetType.GetMethod(methodName) ?? throw new InvalidOperationException($"找不到方法: {methodName}");

      // 调用方法
      object? result = method.Invoke(service, args);

      // 如果是异步方法，等待结果
      if (result is Task task)
      {
        await task;

        // 获取Task<T>的结果
        Type taskType = task.GetType();
        if (taskType.IsGenericType && taskType.GetGenericTypeDefinition() == typeof(Task<>))
        {
          PropertyInfo? resultProperty = taskType.GetProperty("Result");
          return resultProperty?.GetValue(task);
        }

        return null;
      }

      return result;
    }

    private async Task<object> InvokeRpcMethodAsync(string methodName, object[] args, Type resultType)
    {
      // 获取RPC客户端
      IRpcClient rpcClient = await _rpcClientManager.GetRpcClientAsync(_serviceName) ?? throw new InvalidOperationException($"无法获取RPC客户端: {_serviceName}");

      // 创建RPC请求
      TccActionRequest request = new()
      {
        ServiceName = _serviceName,
        MethodName = methodName,
        Args = args,
        Xid = RootContext.GetXid(),
        Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
      };

      // 发送RPC请求
      var response = await rpcClient.SendAsync<TccActionRequest, TccActionResponse>(request);

      return response == null || !response.Success
              ? throw new InvalidOperationException($"TCC服务调用失败: {response?.Message ?? "未知错误"}")
              : response.Result;
    }

    private BranchType GetBranchType(string methodName)
    {
      // 根据方法名判断分支类型
      if (_configuration != null && methodName.EndsWith(_configuration.TryMethodSuffix))
      {
        return BranchType.TCC_TRY;
      }
      else if (_configuration != null && methodName.EndsWith(_configuration.ConfirmMethodSuffix))
      {
        return BranchType.TCC_CONFIRM;
      }
      else if (_configuration != null && methodName.EndsWith(_configuration.CancelMethodSuffix))
      {
        return BranchType.TCC_CANCEL;
      }

      // 默认为Try阶段
      return BranchType.TCC_TRY;
    }

    /// <summary>
    /// 创建TCC服务代理
    /// </summary>
    /// <typeparam name="T">服务接口类型</typeparam>
    /// <param name="serviceProvider">服务提供者</param>
    /// <param name="transactionManager">事务管理器</param>
    /// <param name="rpcClientManager">RPC客户端管理器</param>
    /// <param name="configuration">TCC服务配置</param>
    /// <returns>服务代理实例</returns>
    public static T Create<T>(
        IServiceProvider serviceProvider,
        ITccTransactionManager transactionManager,
        IRpcClientManager rpcClientManager,
        TccServiceConfiguration configuration) where T : class
    {
      TccServiceProxy? proxy = Create<T, TccServiceProxy>() as TccServiceProxy ?? throw new InvalidOperationException("无法创建TCC服务代理");

      proxy._logger = serviceProvider.GetRequiredService<ILogger<TccServiceProxy>>();
      proxy._transactionManager = transactionManager;
      proxy._rpcClientManager = rpcClientManager;
      proxy._configuration = configuration;
      proxy._targetType = typeof(T);
      proxy._serviceName = configuration.ServiceName ?? typeof(T).Name;

      return proxy as T ?? throw new InvalidOperationException("无法转换代理类型");
    }
  }

  /// <summary>
  /// TCC服务工厂
  /// </summary>
  public class TccServiceFactory(
      IServiceProvider serviceProvider,
      ITccTransactionManager transactionManager,
      IRpcClientManager rpcClientManager,
      ILogger<TccServiceFactory> logger)
  {
    private readonly IServiceProvider _serviceProvider = serviceProvider;
    private readonly ITccTransactionManager _transactionManager = transactionManager;
    private readonly IRpcClientManager _rpcClientManager = rpcClientManager;
    private readonly ILogger<TccServiceFactory> _logger = logger;

    /// <summary>
    /// 创建TCC服务代理
    /// </summary>
    /// <typeparam name="T">服务接口类型</typeparam>
    /// <param name="serviceName">服务名称</param>
    /// <param name="isLocalService">是否是本地服务</param>
    /// <returns>服务代理实例</returns>
    public T CreateService<T>(string? serviceName = null, bool isLocalService = true) where T : class
    {
      TccServiceConfiguration configuration = new()
      {
        ServiceName = serviceName ?? typeof(T).Name,
        IsLocalService = isLocalService
      };

      return TccServiceProxy.Create<T>(_serviceProvider, _transactionManager, _rpcClientManager, configuration);
    }

    /// <summary>
    /// 创建TCC服务代理
    /// </summary>
    /// <typeparam name="T">服务接口类型</typeparam>
    /// <param name="configuration">TCC服务配置</param>
    /// <returns>服务代理实例</returns>
    public T CreateService<T>(TccServiceConfiguration configuration) where T : class
    {
      return TccServiceProxy.Create<T>(_serviceProvider, _transactionManager, _rpcClientManager, configuration);
    }
  }

  /// <summary>
  /// TCC服务配置
  /// </summary>
  public class TccServiceConfiguration
  {
    /// <summary>
    /// 服务名称
    /// </summary>
    public string? ServiceName { get; set; }

    /// <summary>
    /// 是否是本地服务
    /// </summary>
    public bool IsLocalService { get; set; } = true;

    /// <summary>
    /// Try方法后缀
    /// </summary>
    public string TryMethodSuffix { get; set; } = "Try";

    /// <summary>
    /// Confirm方法后缀
    /// </summary>
    public string ConfirmMethodSuffix { get; set; } = "Confirm";

    /// <summary>
    /// Cancel方法后缀
    /// </summary>
    public string CancelMethodSuffix { get; set; } = "Cancel";

    /// <summary>
    /// 超时时间（毫秒）
    /// </summary>
    public int TimeoutMs { get; set; } = 60000;

    /// <summary>
    /// 重试次数
    /// </summary>
    public int RetryCount { get; set; } = 3;
  }

  /// <summary>
  /// TCC动作请求
  /// </summary>
  public class TccActionRequest : AbstractMessage
  {
    public override MessageType MessageType => MessageType.TCC_ACTION_REQUEST;

    /// <summary>
    /// 服务名称
    /// </summary>
    public string? ServiceName { get; set; }

    /// <summary>
    /// 方法名称
    /// </summary>
    public string? MethodName { get; set; }

    /// <summary>
    /// 方法参数
    /// </summary>
    public object[]? Args { get; set; }

    /// <summary>
    /// 事务XID
    /// </summary>
    public string? Xid { get; set; }

    /// <summary>
    /// 时间戳
    /// </summary>
    public long Timestamp { get; set; }

    /// <summary>
    /// 编码消息为字节数组
    /// </summary>
    /// <returns>编码后的字节数组</returns>
    public override byte[] Encode()
    {
      using MemoryStream stream = new();
      using BinaryWriter writer = new(stream);

      // 写入消息类型
      writer.Write((int)MessageType);

      // 写入服务名称
      writer.Write(ServiceName ?? string.Empty);

      // 写入方法名称
      writer.Write(MethodName ?? string.Empty);

      // 写入参数数量
      writer.Write(Args?.Length ?? 0);

      // 写入参数
      if (Args != null)
      {
        foreach (object arg in Args)
        {
          string argJson = JsonSerializer.Serialize(arg);
          byte[] argBytes = System.Text.Encoding.UTF8.GetBytes(argJson);
          writer.Write(argBytes.Length);
          writer.Write(argBytes);
        }
      }

      // 写入XID
      writer.Write(Xid ?? string.Empty);

      // 写入时间戳
      writer.Write(Timestamp);

      return stream.ToArray();
    }

    /// <summary>
    /// 从字节数组解码消息
    /// </summary>
    /// <param name="data">字节数组</param>
    public override void Decode(byte[] data)
    {
      using MemoryStream stream = new(data);
      using BinaryReader reader = new(stream);

      // 跳过消息类型（第一个整数）
      _ = reader.ReadInt32();

      // 读取服务名称
      ServiceName = reader.ReadString();

      // 读取方法名称
      MethodName = reader.ReadString();

      // 读取参数数量
      int argCount = reader.ReadInt32();

      // 读取参数
      if (argCount > 0)
      {
        Args = new object[argCount];
        for (int i = 0; i < argCount; i++)
        {
          int argLength = reader.ReadInt32();
          byte[] argBytes = reader.ReadBytes(argLength);
          string argJson = System.Text.Encoding.UTF8.GetString(argBytes);
          Args[i] = JsonSerializer.Deserialize<object>(argJson);
        }
      }
      else
      {
        Args = [];
      }

      // 读取XID
      Xid = reader.ReadString();

      // 读取时间戳
      Timestamp = reader.ReadInt64();
    }
  }

  /// <summary>
  /// TCC动作响应
  /// </summary>
  public class TccActionResponse : AbstractMessage
  {
    public override MessageType MessageType => MessageType.TCC_ACTION_RESPONSE;

    /// <summary>
    /// 是否成功
    /// </summary>
    public bool Success { get; set; }

    /// <summary>
    /// 错误消息
    /// </summary>
    public string? Message { get; set; }

    /// <summary>
    /// 结果
    /// </summary>
    public object? Result { get; set; }

    /// <summary>
    /// 时间戳
    /// </summary>
    public long Timestamp { get; set; }

    /// <summary>
    /// 编码消息为字节数组
    /// </summary>
    /// <returns>编码后的字节数组</returns>
    public override byte[] Encode()
    {
      using MemoryStream stream = new();
      using BinaryWriter writer = new(stream);

      // 写入消息类型
      writer.Write((int)MessageType);

      // 写入成功标志
      writer.Write(Success);

      // 写入错误消息
      writer.Write(Message ?? string.Empty);

      // 写入结果
      string resultJson = JsonSerializer.Serialize(Result);
      byte[] resultBytes = System.Text.Encoding.UTF8.GetBytes(resultJson);
      writer.Write(resultBytes.Length);
      writer.Write(resultBytes);

      // 写入时间戳
      writer.Write(Timestamp);

      return stream.ToArray();
    }

    /// <summary>
    /// 从字节数组解码消息
    /// </summary>
    /// <param name="data">字节数组</param>
    public override void Decode(byte[] data)
    {
      using MemoryStream stream = new(data);
      using BinaryReader reader = new(stream);

      // 跳过消息类型（第一个整数）
      _ = reader.ReadInt32();

      // 读取成功标志
      Success = reader.ReadBoolean();

      // 读取错误消息
      Message = reader.ReadString();

      // 读取结果
      int resultLength = reader.ReadInt32();
      if (resultLength > 0)
      {
        byte[] resultBytes = reader.ReadBytes(resultLength);
        string resultJson = System.Text.Encoding.UTF8.GetString(resultBytes);
        Result = JsonSerializer.Deserialize<object>(resultJson);
      }

      // 读取时间戳
      Timestamp = reader.ReadInt64();
    }
  }
}